package com.ruoyi.system.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.SysClient;
import com.ruoyi.system.mapper.SysClientDataMinMapper;
import com.ruoyi.system.service.ISysClientService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysClientDataMapper;
import com.ruoyi.system.domain.SysClientData;
import com.ruoyi.system.service.ISysClientDataService;

/**
 * 产线运行记录Service业务层处理
 * 
 * @author spark
 * @date 2023-08-19
 */
@Service
public class SysClientDataServiceImpl implements ISysClientDataService
{

    private static final Logger log = LoggerFactory.getLogger(SysClientDataServiceImpl.class);

    @Autowired
    private SysClientDataMapper sysClientDataMapper;

    @Autowired
    private SysClientDataMinMapper sysClientDataMinMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysClientService sysClientService;

    /**
     * 查询产线运行记录
     * 
     * @param dataId 产线运行记录主键
     * @return 产线运行记录
     */
    @Override
    public SysClientData selectSysClientDataByDataId(Long dataId)
    {
        return sysClientDataMapper.selectSysClientDataByDataId(dataId);
    }

    /**
     * 查询产线运行记录列表
     * 
     * @param sysClientData 产线运行记录
     * @return 产线运行记录
     */
    @DataScope(deptAlias = "d")
    @Override
    public List<SysClientData> selectSysClientDataList(SysClientData sysClientData)
    {
        return sysClientDataMapper.selectSysClientDataList(sysClientData);
    }

    /**
     * 补录运行记录 业务 新增产线运行记录
     * 
     * @param sysClientData 产线运行记录
     * @return 结果
     */
    @Override
    public int insertSysClientData(SysClientData sysClientData)
    {
        SysClient sysClient = sysClientService.selectSysClientByClientId(sysClientData.getClientId());
        sysClientData.setDeptId(sysClient.getDeptId());
        sysClientData.setCreateTime(DateUtils.getNowDate());
        sysClientData.setDelFlag("0");
        Long time = sysClientData.getDataEndTime().getTime()- sysClientData.getDataStartTime().getTime();
        time = time/1000;
        sysClientData.setDurationTime( time.intValue());
        int i = sysClientDataMapper.insertSysClientData(sysClientData);
        if(i>0){
            //补录成功 是否 更新 实时运行状态缓存
            //先查询缓存 缓存不存在  判断补录时间 在当前2分钟内 则缓存一条补录结束时间 开始到当前时间+1分钟  缓存时间为1分钟的记录
            if(null==redisCache.getCacheObject(CacheConstants.WORK_LIEN_ID_STATUS+sysClientData.getWorkLineId())){
                Calendar c = Calendar.getInstance();
                //c.add(Calendar.SECOND,durationTime);
                //当前时间 减去 补录结束时间 大于0 小于2分钟  2*60*1000毫秒
                long s2 = c.getTime().getTime() - sysClientData.getDataEndTime().getTime();
                if(s2 >=0L && s2<=120000L){
                    sysClientData.setDataStartTime(c.getTime());
                    //持续1分钟
                    c.add(Calendar.SECOND,60);
                    sysClientData.setDataEndTime(c.getTime());
                    sysClientData.setDurationTime(60);
                    sysClientData.setUserId(null);
                    redisCache.setCacheObject(CacheConstants.WORK_LIEN_ID_STATUS+sysClientData.getWorkLineId()
                            ,sysClientData,60, TimeUnit.SECONDS);
                }


            }
        }
        return i;
    }
//1000*60 *30
    final long min30=1800000L;
    final long min3= 180000L;

    /**
     *  状态终端 上传 产线运行状态 数据
     * @param sysClientData
     * @return
     */
    @Override
    public int insertSysClientDataByUplaod(SysClientData sysClientData)
    {
        SysClient sysClient = sysClientService.selectSysClientByClientId(sysClientData.getClientId());
        if(null != sysClient){
            sysClientData.setFactoryId(sysClient.getFactoryId());
            sysClientData.setRoomId(sysClient.getRoomId());
            sysClientData.setWorkLineId(sysClient.getWorkLineId());
            sysClientData.setDeptId(sysClient.getDeptId());
        }else{
            throw new ServiceException("终端设备ID无效", HttpStatus.WARN);
        }
        sysClientData.setCreateTime(DateUtils.getNowDate());
        sysClientData.setDelFlag("0");
        //记录每分钟产线数据
        int i = sysClientDataMapper.insertSysClientDataMin(sysClientData);
        if(i>0){
            log.info("1 work_lien_id_status_min:{},缓存对象：{}",sysClientData.getWorkLineId(),sysClientData.toString());
            //记录业务产线每分钟数据 缓存实时实时数据  每秒数据 ，按时间段 每分钟缓存 过期为空，则前端显示 产线异常
            redisCache.setCacheObject(CacheConstants.WORK_LIEN_ID_STATUS_MIN+sysClientData.getWorkLineId(),sysClientData,
                    sysClientData.getDurationTime(), TimeUnit.SECONDS);
            //记录业务产线连续数据 缓存连续状态 1 小时，累积相同状态 半小时插入数据库一次，最大累计半小时为一条记录
            SysClientData cacheObject = (SysClientData)redisCache.getCacheObject(CacheConstants.WORK_LIEN_ID_STATUS + sysClientData.getWorkLineId());
            if(cacheObject!=null){
            log.info("2 获取 work_lien_id_status:{},缓存对象：{}",sysClientData.getWorkLineId(),cacheObject.toString());}
            if(cacheObject != null){
                if (cacheObject.getDataState().equals(sysClientData.getDataState())) {
                    //当前上传时间结束时间 和 缓存开始时间 小于30分钟  继续累计
                    if(sysClientData.getDataEndTime().getTime()-cacheObject.getDataStartTime().getTime()< min30){
                        //累计时间 后更新缓存
                        cacheObject.setDataEndTime(sysClientData.getDataEndTime());
                        cacheObject.setDurationTime(new Long((cacheObject.getDataEndTime().getTime()-cacheObject.getDataStartTime().getTime())/1000L).intValue());
                    }else{
                        //大于30分钟 数据库记录一条累计30分钟 的产线状态数据 重新开始 计时
                        sysClientDataMapper.insertSysClientData(cacheObject);
                        log.info("3-1 缓存数据大于30min 插入记录：{}",cacheObject.toString());
                        if(sysClientData.getDataStartTime().getTime()-cacheObject.getDataEndTime().getTime()>min3){
                            //当前报文的开始时间 减去 上一报文的结束时间大于3分钟 中间时间段状态为异常
                            SysClientData exceptionData = insertExceptionData(sysClientData, cacheObject);
                            log.info("3-2 中断上传数据大于3min 插入异常记录：{}",exceptionData.toString());
                        }
                        //缓存当前 上传数据 时间点 重新计时
                        cacheObject = sysClientData;
                    }
                    redisCache.setCacheObject(CacheConstants.WORK_LIEN_ID_STATUS+sysClientData.getWorkLineId(),cacheObject,
                            8, TimeUnit.HOURS);
                //状态不一致：缓存入库，当前数据记录缓存
                }else{
                    sysClientDataMapper.insertSysClientData(cacheObject);
                    log.info("4-1 状态不一致 插入一缓存记录：{}",cacheObject.toString());
                    if(sysClientData.getDataStartTime().getTime()-cacheObject.getDataEndTime().getTime()>min3){
                        //当前报文的开始时间 减去 上一报文的结束时间大于3分钟 中间时间段状态为异常
                        SysClientData exceptionData = insertExceptionData(sysClientData, cacheObject);
                        log.info("4-2 状态不一致 插入异常日志：{}",exceptionData.toString());
                    }
                    redisCache.setCacheObject(CacheConstants.WORK_LIEN_ID_STATUS+sysClientData.getWorkLineId(),sysClientData,
                            1, TimeUnit.HOURS);
                }
            }else{
                //累计缓存为空：则数据库最近数据 到 当前时间点 无上传数据，默认异常 补异常数据  并缓存当前数据
                redisCache.setCacheObject(CacheConstants.WORK_LIEN_ID_STATUS+sysClientData.getWorkLineId(),sysClientData,
                        8, TimeUnit.HOURS);
                log.info("5 缓存无记录 插入当前请求到缓存：{}",sysClientData.toString());
                //补异常数据,开始时间为数据库记录最大结束时间  结束时间为当前时间   持续为插值
                Date date = sysClientDataMapper.selectSysClientDataByWorkLineId(sysClientData.getWorkLineId());
                sysClientData.setDataStartTime(date);
                sysClientData.setDataEndTime(new Date());
                //单位：秒
                Long  durationTime = (System.currentTimeMillis()-date.getTime())/1000L ;
                sysClientData.setDurationTime(durationTime.intValue());
                sysClientData.setDataState("2");
                sysClientDataMapper.insertSysClientData(sysClientData);
                log.info("5 缓存无记录 插入异常日志：{}",sysClientData.toString());
            }
        }
        return i;
    }

    //插入异常日志
    private SysClientData insertExceptionData(SysClientData sysClientData, SysClientData cacheObject) {
        SysClientData exceptionData = new SysClientData();
        exceptionData.setClientId(sysClientData.getClientId());
        exceptionData.setDataStartTime(cacheObject.getDataEndTime());
        exceptionData.setDataEndTime(sysClientData.getDataStartTime());
        //单位：秒
        Long  durationTime = (sysClientData.getDataStartTime().getTime()- cacheObject.getDataEndTime().getTime())/1000L ;
        exceptionData.setDurationTime(durationTime.intValue());
        exceptionData.setDataState("2");
        exceptionData.setWorkLineId(sysClientData.getWorkLineId());
        exceptionData.setClientId(sysClientData.getClientId());
        exceptionData.setDeptId(sysClientData.getDeptId());
        exceptionData.setRoomId(sysClientData.getRoomId());
        exceptionData.setFactoryId(sysClientData.getFactoryId());
        exceptionData.setDelFlag("0");
        exceptionData.setLineCode(sysClientData.getLineCode());
        sysClientDataMapper.insertSysClientData(exceptionData);
        return exceptionData;
    }

    /**
     * 修改产线运行记录
     * 
     * @param sysClientData 产线运行记录
     * @return 结果
     */
    @Override
    public int updateSysClientData(SysClientData sysClientData)
    {
        sysClientData.setUpdateTime(DateUtils.getNowDate());
        return sysClientDataMapper.updateSysClientData(sysClientData);
    }

    /**
     * 批量删除产线运行记录
     * 
     * @param dataIds 需要删除的产线运行记录主键
     * @return 结果
     */
    @Override
    public int deleteSysClientDataByDataIds(Long[] dataIds)
    {
        return sysClientDataMapper.deleteSysClientDataByDataIds(dataIds);
    }

    /**
     * 删除产线运行记录信息
     * 
     * @param dataId 产线运行记录主键
     * @return 结果
     */
    @Override
    public int deleteSysClientDataByDataId(Long dataId)
    {
        return sysClientDataMapper.deleteSysClientDataByDataId(dataId);
    }
}
